<template>
  <q-page class="q-pa-md">
    <div class="row items-center">
      <div class="q-pb-md text-h5">{{ pageTitle }}</div>
      <q-space></q-space>
      <search-bar-toggle-btn v-model="searchBarVisibility"></search-bar-toggle-btn>
    </div>
    <!--查询条件-->
    <div v-show="searchBarVisibility" class="q-pa-sm shadow-2 q-mb-md items-center">
      <div class="row q-col-gutter-sm">
        <div class="col-12 col-sm-6 col-md-4 col-lg-3 row q-col-gutter-sm">
          <div class="col-4 text-right searchbar-label">{{$t('文件UUID')}}</div>
          <div class="col-8">
            <q-input v-model="fpsReq.fileUuid" :hide-bottom-space="true" :readonly="listDataLoadingState" clearable
              dense
              :maxlength="60" outlined square stack-label @focus="ui.select" @keyup.enter="loadListData(2)" />
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-3 row q-col-gutter-sm">
          <div class="col-4 text-right searchbar-label">{{$t('存储分类')}}</div>
          <div class="col-8">
            <q-input v-model="fpsReq.storageClass" :hide-bottom-space="true" :readonly="listDataLoadingState" clearable
              dense
              :maxlength="30" outlined square stack-label @focus="ui.select"
              @keyup.enter="loadListData(2)" />
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-3 row q-col-gutter-sm">
          <div class="col-4 text-right searchbar-label">{{$t('存储ID')}}</div>
          <div class="col-8">
            <q-input v-model="fpsReq.storageId" :hide-bottom-space="true" :readonly="listDataLoadingState" clearable
              dense
              :maxlength="30" outlined square stack-label @focus="ui.select" @keyup.enter="loadListData(2)" />
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-3 row q-col-gutter-sm">
          <div class="col-4 text-right searchbar-label">{{$t('上传者')}}</div>
          <div class="col-8">
            <simple-filter-select v-model="fpsReq.userName" :readonly="listDataLoadingState"
              :option-label="item => item.userDisp" :options="$d.userList"
              :search-label-and-value="true" option-value="userName" />
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-3 row q-col-gutter-sm">
          <div class="col-4 text-right searchbar-label">{{$t('文件大小从')}}</div>
          <div class="col-8">
            <q-input v-model="fpsReq.fileSizeBegin" :hide-bottom-space="true" :readonly="listDataLoadingState" clearable
              dense
              :maxlength="30" outlined square stack-label @focus="ui.select"
              @keyup.enter="loadListData(2)" />
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-3 row q-col-gutter-sm">
          <div class="col-4 text-right searchbar-label">{{$t('文件大小至')}}</div>
          <div class="col-8">
            <q-input v-model="fpsReq.fileSizeEnd" :hide-bottom-space="true" :readonly="listDataLoadingState" clearable
              dense
              :maxlength="30" outlined square stack-label @focus="ui.select"
              @keyup.enter="loadListData(2)" />
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-3 row q-col-gutter-sm">
          <div class="col-4 text-right searchbar-label">{{$t('更新时间(起始)')}}</div>
          <div class="col-8">
            <q-input v-model="fpsReq.updateDtBegin" :error="v$.updateDtBegin.$error"
              :error-message="e$(v$.updateDtBegin.$errors)" :hide-bottom-space="true"
              :readonly="listDataLoadingState" clearable dense :maxlength="30" no-error-icon outlined square stack-label>
              <q-menu ref="dtp-container-1" :fit="false" transition-hide="none" transition-show="none">
                <q-date :title="fpsReq.updateDtBegin" @update:model-value="() => $refs['dtp-container-1'].hide()"
                  mask="YYYY-MM-DD" subtitle="当前选中日期" today-btn v-model="fpsReq.updateDtBegin" />
              </q-menu>
              <template v-slot:append>
                <q-icon name="event" />
              </template>
            </q-input>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-3 row q-col-gutter-sm">
          <div class="col-4 text-right searchbar-label">{{$t('更新时间(结束)')}}</div>
          <div class="col-8">
            <q-input v-model="fpsReq.updateDtEnd" :error="v$.updateDtEnd.$error" :readonly="listDataLoadingState"
              :error-message="e$(v$.updateDtEnd.$errors)" :hide-bottom-space="true"
              clearable dense :maxlength="30" no-error-icon outlined square stack-label>
              <q-menu ref="dtp-container-2" :fit="false" transition-hide="none" transition-show="none">
                <q-date :title="fpsReq.updateDtEnd" @update:model-value="() => $refs['dtp-container-2'].hide()"
                  mask="YYYY-MM-DD" subtitle="当前选中日期" today-btn v-model="fpsReq.updateDtEnd" />
              </q-menu>
              <template v-slot:append>
                <q-icon name="event" />
              </template>
            </q-input>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-3 row q-col-gutter-sm">
          <div class="col-4 text-right searchbar-label">{{$t('文件类型')}}</div>
          <div class="col-8">
            <simple-filter-select :options="mimeTypeList" v-model="fpsReq.mimeType" :readonly="listDataLoadingState" />
          </div>
        </div>
      </div>
      <!--查询按钮-->
      <div class="row q-pt-sm">
        <q-btn :disable="listDataLoadingState" color="primary" icon="search" :label="$t('查询')" no-caps
          @click="loadListData(2)" />
      </div>
    </div>
    <!--列表部分-->
    <div class="shadow-2">
      <q-table v-model:pagination="fpsInfo.paginationInfo" v-model:selected="selectedItems"
        :columns="fpsInfo.columnsInfo" :hide-pagination="true" :loading="listDataLoadingState"
        :rows="$d.tableData" :visible-columns="fpsInfo.visibleColumns" binary-state-sort color="primary"
        dense flat row-key="fileUuid" selection="multiple" separator="cell"
        @request="fpsAssist.onDataTableRequest">
        <template v-slot:top="props">
          <!--功能按钮-->
          <div class="q-gutter-sm">
            <q-btn v-if="fx.hasModifyRight('Comm.Fms.Management')" :disable="selectedItems.length === 0" color="red"
              icon="delete_outline" no-caps
              :label="$t('批量删除')" @click="deleteSelectedFiles" />
            <q-btn v-if="fx.hasModifyRight('Comm.Fms.Management')" color="primary" no-caps
              :label="$t('清理无效文件')" @click="cleanFiles" />
            <q-btn v-if="fx.hasModifyRight('Comm.Fms.Management')" color="primary" :label="$t('清理无效记录')"
              @click="cleanRecords" no-caps/>
            <q-btn v-if="fx.hasModifyRight('Comm.Fms.Management')" color="primary" :label="$t('清理无效公文包')"
              @click="cleanInvalidPfps" no-caps/>
          </div>
          <!--填充所有剩余空间-->
          <q-space />
          <div class="q-mr-md row q-col-gutter-md">
            <div class="searchbar-label">{{$t('文件总数:')}}{{ totalFileAmount }}</div>
            <div class="searchbar-label">{{$t('总大小:')}}{{ fmt.fileSizeDisp(totalFileSize) }}</div>
            <div>
              <q-btn :disable="summaryDataLoadingState" :loading="summaryDataLoadingState" dense icon="refresh"
                :title="$t('刷新')"
                unelevated @click="getFmsSummaryInfo" />
            </div>
          </div>
          <table-col-options-cfg v-model:table-columns="fpsInfo.columnsInfo"
            v-model:visible-columns="fpsInfo.visibleColumns"
            @update-col-options-for-save="fpsAssist.saveColOptions"></table-col-options-cfg>
          <q-btn :icon="props.inFullscreen ? 'fullscreen_exit' : 'fullscreen'"
            :ripple="false" :title="props.inFullscreen ? $t('退出全屏') : $t('全屏显示')" class="q-ml-sm" dense flat
            @click="props.toggleFullscreen" />
        </template>
        <!--无数据提示-->
        <template v-slot:no-data>
          <div class="full-width items-center justify-center row">
            <q-icon name="error_outline" />
            {{$t('无数据')}}
            <q-btn :disable="listDataLoadingState" :loading="listDataLoadingState" class="q-ml-sm"
              dense flat icon="refresh" size="sm" :title="$t('刷新')" @click="loadListData"></q-btn>
          </div>
        </template>
        <!--列插槽操作-->
        <template v-slot:body-cell-operation="props">
          <q-td :props="props">
            <a :href="fx.appCfg.apiBaseUrl + '/comm/fms/file/' + props.row.fileUuid">
              <q-btn class="q-mr-xs btn-in-row" color="primary" dense icon="eva-download" :title="$t('下载')" />
            </a>
            <a :href="fx.appCfg.apiBaseUrl + '/comm/fms/file/' + props.row.fileUuid + '?inline=true'"
              target="_blank">
              <q-btn class="q-mr-xs btn-in-row" color="primary" dense icon="search" :title="$t('查看')" />
            </a>
            <q-btn v-if="fx.hasModifyRight('Comm.Fms.Management')" class="btn-in-row" color="red" dense
              icon="delete_outline" :title="$t('删除')" @click="deleteSingleFile(props.row.fileUuid)" />
          </q-td>
        </template>
        <!--列插槽文件大小-->
        <template v-slot:body-cell-fileSize="props">
          <q-td :props="props">
            {{ fmt.fileSizeDisp(props.row.fileSize) }}
          </q-td>
        </template>
        <!--列插槽文件等级-->
        <template v-slot:body-cell-accessLevel="props">
          <q-td :props="props">
            {{
              props.row.accessLevel === 0 ? $t('无限制') : props.row.accessLevel === 1 ? $t('需登录') : props.row.accessLevel === 2 ?
                $t('仅上传者') : props.row.accessLevel === 3 ? $t('询问') : ''
            }}
          </q-td>
        </template>
        <!--列插槽上传者-->
        <template v-slot:body-cell-userName="props">
          <q-td :props="props"> {{fmt.userDisp(props.row.userName, props.row.userDispName)}} </q-td>
        </template>
        <!--分页组件-->
        <template v-slot:bottom>
          <paging-bar :loading-state="listDataLoadingState" :pageNo="fpsReq.pageNo" :pageSize="fpsReq.pageSize"
            :totalAmount="fpsInfo.totalAmount" @go-to-page="fpsNav.gotoPage"
            @pagesize-changed="fpsAssist.onPageSizeChanged" />
        </template>
      </q-table>
    </div>
  </q-page>
</template>

<script lang="ts">
export default {
  name: 'fmsStd'
}
</script>
<script lang="ts" setup>
import {useFpsHelper} from '../../hooks/fpsHelper'
import {useTitleHelper} from '../../hooks/titleHelper'
import {reactive, ref} from 'vue'
import {GetFmsFileListReq, GetFmsFileListResp, FmsFileInfo, FmsSummary} from '../../defs/fms'
import {ColumnInfo, JsonRespBase} from '../../defs/comm'
import _ from 'lodash'
import useVuelidate from '@vuelidate/core'
import {SimUserInfo} from '../../helper/dropdownlist.d'
import {useI18n} from 'vue-i18n'

const {t} = useI18n()

const pageTitle = t('文件管理')
useTitleHelper(pageTitle)

// 查询参数
const fpsReq: GetFmsFileListReq = reactive({
  fileUuid: null,
  storageClass: null,
  storageId: null,
  userName: null,
  mimeType: null,
  fileSizeBegin: null,
  fileSizeEnd: null,
  updateDtBegin: null,
  updateDtEnd: null,
  pageNo: 1,
  pageSize: 40,
  isDescending: false,
  orderBy: null
})

//查询参数日期格式验证
const validators = $f.validators
const rules = {
  updateDtBegin: {
    date: validators.date
  },
  updateDtEnd: {
    date: validators.date
  }
}
const v$ = useVuelidate(rules, fpsReq, {$autoDirty: true})

// 列参数
const columnsDefine: ColumnInfo[] = [
  {
    label: t('操作'),
    name: 'operation',
    field: 'operation',
    align: 'left',
    defOrder: 1,
    defVisible: true
  },
  {
    label: t('文件UUID'),
    name: 'fileUuid',
    field: 'fileUuid',
    align: 'left',
    defOrder: 2,
    defVisible: true
  },
  {
    label: t('原始文件名称'),
    name: 'originalFileName',
    field: 'originalFileName',
    align: 'left',
    defOrder: 3,
    defVisible: true
  },
  {
    label: t('存储分类'),
    name: 'storageClass',
    field: 'storageClass',
    sortable: true,
    align: 'left',
    defOrder: 4,
    defVisible: true
  },
  {
    label: t('存储ID'),
    name: 'storageId',
    field: 'storageId',
    sortable: true,
    align: 'left',
    defOrder: 5,
    defVisible: true
  },
  {
    label: t('上传者'),
    name: 'userName',
    field: 'userName',
    sortable: true,
    align: 'left',
    defOrder: 6,
    defVisible: true
  },
  {
    label: t('文件访问等级'),
    name: 'accessLevel',
    field: 'accessLevel',
    align: 'left',
    defOrder: 7,
    defVisible: true
  },
  {
    label: t('MIME类型'),
    name: 'mimeType',
    field: 'mimeType',
    sortable: true,
    align: 'left',
    defOrder: 8,
    defVisible: true
  },
  {
    label: t('文件大小'),
    name: 'fileSize',
    field: 'fileSize',
    sortable: true,
    align: 'left',
    defOrder: 9,
    defVisible: true
  },
  {
    label: t('备注'),
    name: 'comment',
    field: 'comment',
    align: 'left',
    defOrder: 10,
    defVisible: true
  },
  {
    label: t('内部标识'),
    name: 'internalFlag',
    field: 'internalFlag',
    align: 'left',
    defOrder: 11,
    defVisible: true
  },
  {
    label: t('创建日期'),
    name: 'createDt',
    field: 'createDt',
    align: 'left',
    defOrder: 12,
    defVisible: true,
    format: (value: any) => $f.fmt.dtFmtDateOnly(value as string)
  },
  {
    label: t('更新日期'),
    name: 'updateDt',
    field: 'updateDt',
    sortable: true,
    align: 'left',
    defOrder: 13,
    defVisible: true,
    format: (value: any) => fmt.dtFmtDateOnly(value as string)
  }
]

const $d = reactive({
  tableData: [] as FmsFileInfo[],
  userList: [] as SimUserInfo[]
})

//清理无效文件
const cleanFiles = function () {
  void $f.ui.messageBox({
    caption: t('操作确认'),
    text: t('确定要清理无效文件吗?'),
    icon: 'Warning',
    buttons: 'OkCancel',
    delayClose: true
  }).then((btn) => {
    if (btn === 'ok') {
      $f.axios
        .post<JsonRespBase>('/comm/fms/clean-invalid-files')
        .then((result) => {
          void $f.ui.messageBox({
            caption: t('清理成功'),
            text: result.data.msg,
            icon: 'Succeeded',
            buttons: 'Close'
          }).then(() => {
            loadListData()
          })
        })
        .catch((err) => {
          void $f.ui.messageBox({
            caption: t('清理失败'),
            text: $f.getAxiosErrMsg(err),
            icon: $f.getAxiosErrIcon(err),
            buttons: 'Close'
          })
        })
    }
  })
}

// 清理无效公文包
const cleanInvalidPfps = function () {
  void $f.ui.messageBox({
    caption: t('操作确认'),
    text: t('确定要清理无效公文包吗?'),
    icon: 'Warning',
    buttons: 'OkCancel',
    delayClose: true
  }).then((btn) => {
    if (btn === 'ok') {
      $f.axios
        .post<JsonRespBase>('/comm/fms/clean-invalid-pfps')
        .then((result) => {
          void $f.ui.messageBox({
            caption: t('清理成功'),
            text: result.data.msg,
            icon: 'Succeeded',
            buttons: 'Close'
          }).then(()=>{
            loadListData()
          })
        })
        .catch((err) => {
          void $f.ui.messageBox({
            caption: t('清理失败'),
            text: $f.getAxiosErrMsg(err),
            icon: $f.getAxiosErrIcon(err),
            buttons: 'Close'
          })
        })
    }
  })
}

// 清理无效记录
const cleanRecords = function () {
  void $f.ui.messageBox({
    caption: t('操作确认'),
    text: t('确定要清理无效记录吗?'),
    icon: 'Warning',
    buttons: 'OkCancel',
    delayClose: true
  }).then((btn) => {
    if (btn === 'ok') {
      $f.axios
        .post<JsonRespBase>('/comm/fms/clean-invalid-records')
        .then((result) => {
          void $f.ui.messageBox({
            caption: t('清理成功'),
            text: result.data.msg,
            icon: 'Succeeded',
            buttons: 'Close'
          }).then(()=>{
            loadListData()
          })
        })
        .catch((err) => {
          void $f.ui.messageBox({
            caption: t('清理失败'),
            text: $f.getAxiosErrMsg(err),
            icon: $f.getAxiosErrIcon(err),
            buttons: 'Close'
          })
        })
    }
  })
}

// 删除单个文件
const deleteSingleFile = function (fileUuidToDel: string) {
  doDeleteFiles([fileUuidToDel])
}

const selectedItems = ref([])
// 删除选中的文件
const deleteSelectedFiles = function () {
  doDeleteFiles(_.map(selectedItems.value, 'fileUuid'))
}

// 执行删除
const doDeleteFiles = function (fileUuidsToDel: string[]) {
  void $f.ui.messageBox({
    caption: t('操作确认'),
    text: t('确定要删这{number}个文件吗?', {number: fileUuidsToDel.length.toString()}),
    icon: 'Warning',
    buttons: 'OkCancel',
    delayClose: true
  }).then((btn) => {
    if (btn === 'ok') {
      $f.axios
        .post('/comm/fms/delete-files-mgr', {fileUuids: fileUuidsToDel})
        .then(() => {
          void $f.ui.closeMsgBox()
          loadListData()
        })
        .catch((err) => {
          void $f.ui.messageBox({
            caption: t('删除失败'),
            text: $f.getAxiosErrMsg(err),
            icon: $f.getAxiosErrIcon(err),
            buttons: 'Close'
          })
        })
    }
  })
}

//统计文件的总数量和大小
let totalFileAmount = ref(0)
let totalFileSize = ref(0)
let summaryDataLoadingState = ref(false)
const getFmsSummaryInfo = function () {
  summaryDataLoadingState.value = true
  $f.axios
    .get<FmsSummary>('/comm/fms/get-fms-summary')
    .then((result) => {
      totalFileAmount.value = result.data.totalFileAmount
      totalFileSize.value = result.data.totalFileSize
    })
    .catch((err) => {
      $f.ui.showNotifyFailed($f.getAxiosErrMsg(err))
    })
    .finally(() => {
      summaryDataLoadingState.value = false
    })
}

// 是否处于数据列表加载的状态
const listDataLoadingState = ref(false)
const loadListData = function (resetFpsReq?: number) {
  if (resetFpsReq) {
    if (resetFpsReq >= 1) {
      fpsReq.pageNo = 1
    }
    if (resetFpsReq >= 2) {
      fpsReq.orderBy = ''
      fpsReq.isDescending = false
    }
  }
  listDataLoadingState.value = true
  $f.axios.get<GetFmsFileListResp>('/comm/fms/get-fms-file-list', {params: fpsReq})
    .then((result) => {
      selectedItems.value = [] // 清除选中的条目
      if (result.data.updateDtBegin != null) {
        result.data.updateDtBegin = fmt.dtFmtDateOnly(result.data.updateDtBegin)
      }
      if (result.data.updateDtEnd != null) {
        result.data.updateDtEnd = fmt.dtFmtDateOnly(result.data.updateDtEnd)
      }
      fpsAssist.handleGenericFpsResp(result.data)
      $d.tableData = result.data.data
      fpsAssist.saveFpsReq(fpsReq)
    })
    .catch((err) => {
      $f.ui.showNotifyFailed($f.getAxiosErrMsg(err))
    })
    .finally(() => {
      listDataLoadingState.value = false
    })
}

//region FPS配置
const {
  fpsInfo,
  fpsAssist,
  fpsNav,
  searchBarVisibility
} = useFpsHelper('/comm/cfg/fms',
  null,
  null,
  null,
  fpsReq, columnsDefine,
  null,
  loadListData)
//endregion

// region 初始化
getFmsSummaryInfo()
// 获取用户
void $f.lst.getSimUserInfoList(true).then((resp) => {
  $d.userList = resp
}).catch((err) => {
  $f.ui.showNotifyFailed($f.getAxiosErrMsg(err))
})

//文件类型下拉数据源
const mimeTypeList = [
  {
    label: 'ZIP压缩包文件(zip)',
    value: 'application/zip'
  },
  {
    label: 'XML文本文件(xml)',
    value: 'application/xml'
  },
  {
    label: 'JSON文本文件(json)',
    value: 'application/json'
  },
  {
    label: 'JPEG图片文件(jpg)',
    value: 'image/jpeg'
  },
  {
    label: 'PNG图片文件(png)',
    value: 'image/png'
  },
  {
    label: 'SVG图片文件(svg)',
    value: 'image/svg+xml'
  },
  {
    label: 'GIF图片文件(gif)',
    value: 'image/gif'
  },
  {
    label: '普通文本文件(txt)',
    value: 'text/plain'
  },
  {
    label: '其它二进制格式',
    value: 'application/octet-stream'
  },
  {
    label: 'Word 97/2003格式(doc)',
    value: 'application/msword'
  },
  {
    label: 'Excel 97/2003格式(doc)',
    value: 'application/vnd.ms-excel'
  },
  {
    label: 'PowerPoint 97/2003格式(ppt)',
    value: 'application/vnd.ms-powerpoint'
  },
  {
    label: 'Visio 旧格式(vsd)',
    value: 'application/vnd.visio'
  },
  {
    label: 'Access数据库 97/2003格式(mdb)',
    value: 'application/vnd.ms-access'
  },
  {
    label: 'Word 2007格式(docx)',
    value: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
  },
  {
    label: 'Excel 2007格式(xlsx)',
    value: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  },
  {
    label: 'PowerPoint 2007格式(pptx)',
    value: 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
  },
  {
    label: 'Visio 新格式(vsdx)',
    value: 'application/vnd.ms-visio.drawing'
  },
  {
    label: 'PDF格式(pdf)',
    value: 'application/pdf'
  }
]

const fx = $f
const ui = $f.ui
const fmt = $f.fmt
const e$ = $f.getFieldErrStr
// endregion

</script>
